home *** CD-ROM | disk | FTP | other *** search
- #include <Devices.h>
- #include <Fonts.h>
- #include <LowMem.h>
- #include <ImageCompression.h>
- #include <Movies.h>
- #include <NumberFormatting.h>
- #include <Processes.h>
-
- Boolean gDecompressingSourceFrame;
- Boolean gCompressingSourceFrame;
- Boolean gDecompressingToScreen;
-
- Boolean getMovieFile(FSSpec *theFile);
- OSErr OpenSelection(FSSpecPtr theDocToOpen);
-
- pascal void decompressSrcFrameDone(OSErr result, short flags, long refcon);
- pascal void compressSrcFrameDone(OSErr result, short flags, long refcon);
- pascal void decompressToScreenDone(OSErr result, short flags, long refcon);
-
- Boolean fPeriodic( WindowRef theWindow, Rect *whiteRect, TimeValue srcMovieDuration, TimeValue timeNow );
- void fSetRGBColor( RGBColor *theColor, short r, short g, short b );
- void fPNumToString( float theNum, Str255 theString, short fix );
- void fPStrCopy( Str255 s1, Str255 s2 );
- void fPStrConcat( Str255 s1, Str255 s2 );
-
- #define MAX_SAMPLES 60
-
- typedef struct {
- long duration; // in milliseconds
- long size; // sample size in bytes
- } SampleRecord;
-
- typedef struct {
- long duration;
- long fileOffset;
- long dataSize;
- Boolean isKeyFrame;
- char pad[3];
- } SampleEntryRecord, **SampleEntry;
-
- void main(void)
- {
- OSErr err;
- FSSpec file;
- Movie m;
- short resFref;
- WindowPtr w;
- Rect bounds;
- Track srcVideoTrack = nil;
- Media srcVideoMedia;
- Track dstVideoTrack = nil;
- GWorldPtr gw[3];
- ImageDescriptionHandle srcDesc = nil;
- ImageSequence srcDecoSequences[3];
- TimeValue timeNow;
- TimeValue srcMovieDuration;
- Handle srcVideoData1 = NewHandle(0);
- Handle srcVideoData2 = NewHandle(0);
- CodecFlags outFlags;
- long srcVideoDataSize1, srcVideoDataSize2;
- TimeValue mediaTimeNow;
- Boolean useFirstBufferForCompress;
- ICMCompletionProcRecord srcDecoCompletion, compressCompletion, screenDecoCompletion;
- ImageDescriptionHandle compressedDesc = nil;
- ImageSequence compSequence = 0;
- long maxCompressionBufferSize;
- Handle compressedData1 = nil, compressedData2 = nil;
- long compressedDataSize1 = 0, compressedDataSize2 = 0;
- UInt8 compressedSimilarity1, compressedSimilarity2;
- ImageSequence screenDecoSequence = 0;
- long i;
- long currentCompressGWorldIndex;
- long currentDecompressGWorldIndex;
- DataRateParams dataRateStuff;
- long sampleCount = 0;
- SampleRecord sampleRecords[MAX_SAMPLES];
- long totalDuration = 0, totalSize = 0;
- SampleEntry theSampleRefs = (SampleEntry)NewHandle(0);
- long currentFileOffset = 0;
- short outputFref = 0;
- IOParam writeBlock;
- short outputResRef = -1;
- Movie newMovie = nil;
- Rect whiteRect;
- FSSpec newFile;
-
- Handle compressedFrameDurations = NewHandle(0);
- Handle compressedFrameSize = NewHandle(0);
-
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(0L);
- InitCursor();
- MaxApplZone();
-
- EnterMovies();
-
- if (!getMovieFile(&file))
- return;
-
- SetRect(&bounds, 75, 75, 75+160,75+120);
- w = NewCWindow(nil, &bounds, file.name, false, 0, (WindowPtr)-1,
- true, 0);
- if (!w) return;
-
- SetPort(w);
-
- err = OpenMovieFile(&file, &resFref, fsRdPerm);
- if (err) return;
-
- err = NewMovieFromFile(&m, resFref, nil, (StringPtr)nil,
- newMovieActive, nil);
- if (err) return;
-
- CloseMovieFile(resFref);
-
- // create the output file
- newFile = file;
- newFile.name[++newFile.name[0]] = '!';
- err = CreateMovieFile(&newFile, 'TVOD', -1, createMovieFileDeleteCurFile, &outputResRef, &newMovie);
- if (err) return;
-
- err = FSpOpenDF(&newFile, fsRdWrPerm, &outputFref);
- if (err) return;
-
- writeBlock.ioResult = 0;
-
- GetMovieBox(m, &bounds);
- OffsetRect(&bounds, -bounds.left, -bounds.top);
- SetMovieBox(m, &bounds);
-
- whiteRect = bounds;
- whiteRect.bottom += 120;
-
- SizeWindow(w, bounds.right, whiteRect.bottom, false);
- ShowWindow(w);
-
- whiteRect.top = whiteRect.bottom;
-
- for (i=0; i<3; i++) {
- err = NewGWorld(&gw[i], 32, &bounds, nil, nil, 0);
- if (err) {
- err = NewGWorld(&gw[i], 32, &bounds, nil, nil, useTempMem);
- if (err) return;
- }
- LockPixels(gw[i]->portPixMap);
- }
-
- srcVideoTrack = GetMovieIndTrackType(m, 1, 'vide', movieTrackEnabledOnly | movieTrackMediaType);
- if (!srcVideoTrack) return;
-
- srcVideoMedia = GetTrackMedia(srcVideoTrack);
- srcDesc = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
- if (!srcDesc) return;
- GetMediaSampleDescription(srcVideoMedia, 1, (SampleDescriptionHandle)srcDesc);
-
- for (i=0; i<3; i++) {
- err = DecompressSequenceBegin(&srcDecoSequences[i], srcDesc, gw[i], nil, nil, nil, ditherCopy, nil, 0, codecNormalQuality, anyCodec);
- if (err) return;
- }
-
- srcDecoCompletion.completionProc = NewICMCompletionProc(decompressSrcFrameDone);
- srcDecoCompletion.completionRefCon = (long)&gDecompressingSourceFrame;
- gDecompressingSourceFrame = false;
-
- compressCompletion.completionProc = NewICMCompletionProc(compressSrcFrameDone);
- compressCompletion.completionRefCon = (long)&gCompressingSourceFrame;
- gCompressingSourceFrame = false;
-
- screenDecoCompletion.completionProc = NewICMCompletionProc(decompressToScreenDone);
- screenDecoCompletion.completionRefCon = (long)&gDecompressingToScreen;
- gDecompressingToScreen = false;
-
- compressedDesc = (ImageDescriptionHandle)NewHandle(0);
- if (!compressedDesc) return;
-
- err = CompressSequenceBegin(&compSequence, gw[0]->portPixMap, nil, nil, nil, 24, 'cvid', anyCodec, codecLosslessQuality - 1, codecLosslessQuality - 1, 15, nil, codecFlagUpdatePreviousComp, compressedDesc);
- if (err) return;
-
- err = GetMaxCompressionSize(gw[0]->portPixMap, &gw[0]->portRect, 24, codecLosslessQuality - 1, 'cvid', anyCodec, &maxCompressionBufferSize);
- if (err) return;
-
- compressedData1 = NewHandle(maxCompressionBufferSize);
- compressedData2 = NewHandle(maxCompressionBufferSize);
- if (!compressedData1 || !compressedData2)
- return;
-
- HLockHi(compressedData1);
- HLockHi(compressedData2);
-
- dataRateStuff.dataRate = 260 * 1024;
- dataRateStuff.keyFrameRate = 60;
- dataRateStuff.minSpatialQuality = codecLosslessQuality - 1;
- dataRateStuff.minTemporalQuality = codecLosslessQuality - 1;
- totalDuration = 1000;
- totalSize = dataRateStuff.dataRate;
- sampleRecords[0].size = dataRateStuff.dataRate;
- sampleRecords[0].duration = 1000;
- sampleCount = 1;
-
- srcMovieDuration = GetMovieDuration(m);
- timeNow = 0;
-
- // prime the loop by decompressing the first frame into the first gworld
- mediaTimeNow = TrackTimeToMediaTime(timeNow, srcVideoTrack);
- if (mediaTimeNow == -1) return;
-
- err = GetMediaSample(srcVideoMedia, srcVideoData1, 0, &srcVideoDataSize1, mediaTimeNow, nil, nil, nil, nil, 1, nil, nil);
- if (err) return;
-
- HLock(srcVideoData1);
- err = DecompressSequenceFrameS(srcDecoSequences[0], *srcVideoData1, srcVideoDataSize1, 0, &outFlags, nil);
- if (err) return;
-
- HUnlock(srcVideoData1);
-
- // figure out the next frame time
- GetTrackNextInterestingTime(srcVideoTrack, nextTimeMediaSample | nextTimeIgnoreActiveSegment, timeNow, 1, &timeNow, nil);
- if (timeNow == -1) return;
-
- // load the next frame to decompress
- mediaTimeNow = TrackTimeToMediaTime(timeNow, srcVideoTrack);
- if (mediaTimeNow == -1) return;
-
- err = GetMediaSample(srcVideoMedia, srcVideoData1, 0, &srcVideoDataSize1, mediaTimeNow, nil, nil, nil, nil, 1, nil, nil);
- if (err) return;
-
- // initialize more stuff
- useFirstBufferForCompress = true;
- currentCompressGWorldIndex = 0;
- currentDecompressGWorldIndex = 1;
-
- while (timeNow < srcMovieDuration) {
- TimeValue mediaTimeNow = TrackTimeToMediaTime(timeNow, srcVideoTrack);
-
- if( fPeriodic( w, &whiteRect, srcMovieDuration, timeNow ) )
- break;
-
- if (mediaTimeNow != -1) {
- // wait for last source frame to finish decompressing
- while (gDecompressingSourceFrame)
- ;
-
- // start that next source frame decompressing
- gDecompressingSourceFrame = true;
- HLock(useFirstBufferForCompress ? srcVideoData1 : srcVideoData2);
- err = DecompressSequenceFrameS(srcDecoSequences[currentDecompressGWorldIndex],
- useFirstBufferForCompress ? *srcVideoData1 : *srcVideoData2,
- useFirstBufferForCompress ? srcVideoDataSize1 : srcVideoDataSize2, 0, &outFlags, &srcDecoCompletion);
- if (err) return;
-
- // read next source frame
- HUnlock(useFirstBufferForCompress ? srcVideoData2 : srcVideoData1);
- err = GetMediaSample(srcVideoMedia, useFirstBufferForCompress ? srcVideoData2 : srcVideoData1,
- 0, useFirstBufferForCompress ? &srcVideoDataSize2 : &srcVideoDataSize1, mediaTimeNow, nil, nil, nil, nil, 1, nil, nil);
- if (err) return;
-
- // wait for last compress to finish compressing
- while (gCompressingSourceFrame)
- ;
-
- // figure out the data rate parameters for this next frame
- if (sampleCount < MAX_SAMPLES) {
- SampleRecord *srp = &sampleRecords[sampleCount];
- srp->duration = 33; //•• evil
- srp->size = useFirstBufferForCompress ? compressedDataSize2 : compressedDataSize1;
- totalDuration += 33; //•• evil
- totalSize += srp->size;
- sampleCount++;
- }
-
- // drop (totalDuration - 1000) worth of sample data
- {
- long n = totalDuration - 1000;
- while (n && totalDuration && sampleCount) {
- if (n - sampleRecords[0].duration >= 0) {
- short i;
- n -= sampleRecords[0].duration;
- totalDuration -= sampleRecords[0].duration;
- totalSize -= sampleRecords[0].size;
- for (i = 1; i < sampleCount; i++)
- sampleRecords[i-1] = sampleRecords[i];
- sampleCount--;
- } else {
- long dec = n * sampleRecords[0].size / sampleRecords[0].duration;
- sampleRecords[0].size -= dec;
- sampleRecords[0].duration -= n;
- totalSize -= dec;
- totalDuration -= n;
- n = 0;
- }
- }
- }
-
- dataRateStuff.dataOverrun = totalSize - dataRateStuff.dataRate;
- dataRateStuff.frameDuration = 33; //•• evil
- SetCSequenceDataRateParams(compSequence, &dataRateStuff);
-
- if (screenDecoSequence) {
- // write out to disk the most recently compressed frame
- SampleEntryRecord ser;
-
- ser.duration = 33; //•• evil
- ser.fileOffset = currentFileOffset;
- ser.dataSize = useFirstBufferForCompress ? compressedDataSize2 : compressedDataSize1;
- ser.isKeyFrame = (useFirstBufferForCompress ? compressedSimilarity2 : compressedSimilarity1) == 0;
- err = PtrAndHand(&ser, (Handle)theSampleRefs, sizeof(ser));
- if (err) break;
-
- // wait for previous write to complete
- while (writeBlock.ioResult == 1)
- ;
-
- if (writeBlock.ioResult != noErr) return;
-
- writeBlock.ioRefNum = outputFref;
- writeBlock.ioPosMode = fsFromStart;
- writeBlock.ioPosOffset = currentFileOffset;
- writeBlock.ioReqCount = ser.dataSize;
- writeBlock.ioBuffer = useFirstBufferForCompress ? *compressedData2 : *compressedData1;
- writeBlock.ioCompletion = nil;
-
- PBWriteAsync((ParmBlkPtr)&writeBlock);
-
- currentFileOffset += ser.dataSize;
- }
-
- // compress last source frame
- err = SetCSequencePrev(compSequence, gw[(currentCompressGWorldIndex + 2) % 3]->portPixMap, &gw[0]->portRect);
- if (err) return;
-
- err = CompressSequenceFrame(compSequence, gw[currentCompressGWorldIndex]->portPixMap,
- nil, codecFlagUpdatePreviousComp, useFirstBufferForCompress ? *compressedData1 : *compressedData2,
- useFirstBufferForCompress ? &compressedDataSize1 : &compressedDataSize2,
- useFirstBufferForCompress ? &compressedSimilarity1 : &compressedSimilarity2,
- &compressCompletion);
- if (err) return;
-
- // wait for decompress to screen frame to finish decompressing
- while (gDecompressingToScreen)
- ;
-
- // probably decompress the last compressed frame to the screen
- if (!screenDecoSequence) {
- // first time around, just make up the decompress sequence
- err = DecompressSequenceBegin(&screenDecoSequence, compressedDesc, (CGrafPtr)w, nil, nil, nil, ditherCopy, nil, 0, codecNormalQuality, anyCodec);
- if (err) return;
- }
- else {
- // all other times, decompress last compressed frame to screen
- gDecompressingToScreen = true;
- err = DecompressSequenceFrameS(screenDecoSequence,
- useFirstBufferForCompress ? *compressedData2 : *compressedData1,
- useFirstBufferForCompress ? compressedDataSize2 : compressedDataSize1, 0, &outFlags, &screenDecoCompletion);
- if (err) return;
- }
-
- useFirstBufferForCompress = !useFirstBufferForCompress;
- currentCompressGWorldIndex = (currentCompressGWorldIndex + 1) % 3;
- currentDecompressGWorldIndex = (currentDecompressGWorldIndex + 1) % 3;
- }
-
- GetTrackNextInterestingTime(srcVideoTrack, nextTimeMediaSample | nextTimeIgnoreActiveSegment, timeNow, 1, &timeNow, nil);
- if (timeNow == -1)
- timeNow = srcMovieDuration;
- }
-
- fPeriodic( w, &whiteRect, srcMovieDuration, timeNow );
-
- {
- long sampleCount = GetHandleSize((Handle)theSampleRefs) / sizeof(SampleEntryRecord);
- long i;
- Track dstVideoTrack;
- Media dstVideoMedia;
-
- dstVideoTrack = NewMovieTrack(newMovie, (**compressedDesc).width << 16, (**compressedDesc).height << 16, 0);
- dstVideoMedia = NewTrackMedia(dstVideoTrack, 'vide', 1000, nil, 0);
-
- for (i=0; i<sampleCount; i++) {
- SampleEntryRecord ser = (*theSampleRefs)[i];
-
- err = AddMediaSampleReference(dstVideoMedia, ser.fileOffset, ser.dataSize, ser.duration, (SampleDescriptionHandle)compressedDesc,
- 1, ser.isKeyFrame ? 0 : mediaSampleNotSync, nil);
- if (err) return;
- }
-
- err = InsertMediaIntoTrack(dstVideoTrack, 0, 0, GetMediaDuration(dstVideoMedia), 1 << 16);
- if (err) return;
-
- // copy over all other tracks (by reference)
- for (i=1; i<=GetMovieTrackCount(m); i++) {
- Track t = GetMovieIndTrack(m, i);
- Track newTrack;
-
- if (t == srcVideoTrack)
- continue;
-
- AddEmptyTrackToMovie(t, newMovie, nil, 0, &newTrack);
- InsertTrackSegment(t, newTrack, 0, GetMovieDuration(newMovie), 0);
- }
-
- err = AddMovieResource(newMovie, outputResRef, nil, nil);
- if (err) return;
- }
-
- OpenSelection(&newFile);
-
- bail:
- CDSequenceEnd(screenDecoSequence);
-
- for (i=0; i<3; i++)
- CDSequenceEnd(srcDecoSequences[i]);
-
- CDSequenceEnd(compSequence);
-
- if (outputFref) FSClose(outputFref);
- if (outputResRef != -1) CloseMovieFile(outputResRef);
-
- if (newMovie) DisposeMovie(newMovie);
- }
-
- pascal void decompressSrcFrameDone(OSErr /* result */, short flags, long refcon)
- {
- Boolean *decompressingFlag = (Boolean *)refcon;
-
- if (flags & codecCompletionDest)
- *decompressingFlag = false;
- }
-
- pascal void compressSrcFrameDone(OSErr /* result */, short flags, long refcon)
- {
- Boolean *compressingFlag = (Boolean *)refcon;
-
- if (flags & codecCompletionDest)
- *compressingFlag = false;
- }
-
- pascal void decompressToScreenDone(OSErr /* result */, short flags, long refcon)
- {
- Boolean *decompressingFlag = (Boolean *)refcon;
- if (flags & codecCompletionDest)
- *decompressingFlag = false;
- }
-
- /*==================================================================================*/
- Boolean fPeriodic( WindowRef theWindow, Rect *whiteRect, TimeValue srcMovieDuration, TimeValue timeNow ) {
- /* Check for events, update progress bar. Return true to quit program. */
-
- #define kTimeStamps 30
-
- long i;
- Boolean quit;
- EventRecord theEvent;
- RGBColor theColor;
- float framesPerSecond;
- long startTick;
- long endTick;
- Str255 theString;
- WindowRef aWindow;
- long startMovieTime;
- static gSetup;
- static Rect gTheRect;
- static Rect gTextRect;
- static Rect gMPTextRect;
- static Rect gTimeRemainingTextRect;
- static Rect gFillRect;
- static long gTimeStamps[kTimeStamps];
- static long gNextStamp;
- unsigned long gInitialTick;
- static long gMovieTimes[kTimeStamps];
-
- quit = false;
-
- /* Check for events */
- if( OSEventAvail( mDownMask | keyDownMask, &theEvent) ) {
- GetNextEvent(mDownMask | keyDownMask, &theEvent);
- switch( theEvent.what ) {
- case mouseDown:
- if (FindWindow( theEvent.where, &aWindow ) == inGoAway) {
- if (TrackGoAway(aWindow, theEvent.where))
- quit = true;
- }
- break;
- case keyDown:
- if( theEvent.modifiers & cmdKey )
- if( (char)theEvent.message == 'Q' ||
- (char)theEvent.message == 'q' ||
- (char)theEvent.message == '.' )
- quit = true;
- break;
- }
- }
-
- /* Draw progress the first time */
- if( !gSetup ) {
- gTheRect = *whiteRect;
- gTheRect.left += 20;
- gTheRect.bottom -= 20;
- gTheRect.top = gTheRect.bottom - 20;
- gTheRect.right -= 80;
- gTextRect = gTheRect;
- OffsetRect( &gTextRect, 0, -40 );
- gMPTextRect = gTheRect;
- OffsetRect( &gMPTextRect, 0, -60 );
- #if 0
- gTimeRemainingTextRect = gTheRect;
- OffsetRect( &gTimeRemainingTextRect, 0, -40 );
- #endif
- FrameRect( &gTheRect );
- InsetRect( &gTheRect, 1, 1 );
- gFillRect = gTheRect;
- if( theWindow->portBits.rowBytes < 0 )
- if( (*((CGrafPtr)theWindow)->portPixMap)->pixelSize > 1 ) {
- fSetRGBColor( &theColor, 205, 205, 255 );
- RGBForeColor( &theColor );
- PaintRect( &gFillRect );
- fSetRGBColor( &theColor, 0, 0, 0 );
- RGBForeColor( &theColor );
- }
-
- for( i = 0; i < kTimeStamps; i++ )
- gTimeStamps[i] = -1;
- gNextStamp = 0;
-
- MoveTo( gTextRect.left, gTextRect.bottom );
- DrawString( "\pFrames per second: " );
- gTextRect.left += StringWidth( "\pFrames per second: " );
-
- MoveTo( gMPTextRect.left, gMPTextRect.bottom );
- DrawString( "\pProcessors in use: " );
- gMPTextRect.left += StringWidth( "\pProcessors in use: " );
- #if 0
- MoveTo( gTimeRemainingTextRect.left, gTimeRemainingTextRect.bottom );
- DrawString( "\pTime remaining: " );
- gTimeRemainingTextRect.left += StringWidth( "\pTime remaining: " );
- #endif
- gInitialTick = LMGetTicks();
-
- gSetup = true;
- }
-
- /* Update progress the rest of the time */
- else {
-
- gFillRect.right = gTheRect.left + (gTheRect.right - gTheRect.left) *
- timeNow / (float)srcMovieDuration;
- fSetRGBColor( &theColor, 86, 86, 86 );
- RGBForeColor( &theColor );
- PaintRect( &gFillRect );
- fSetRGBColor( &theColor, 0, 0, 0 );
- RGBForeColor( &theColor );
- TextMode(srcCopy);
- TextFace(bold);
-
- startTick = gTimeStamps[gNextStamp];
- endTick = LMGetTicks();
- startMovieTime = gMovieTimes[gNextStamp];
- gMovieTimes[gNextStamp] = timeNow;
- gTimeStamps[gNextStamp++] = endTick;
- if( gNextStamp == kTimeStamps )
- gNextStamp = 0;
- if( startTick != -1 ) {
- framesPerSecond = (kTimeStamps / (float)(endTick - startTick)) * 60.0;
- fPNumToString( framesPerSecond, theString, 2 );
- MoveTo( gTextRect.left, gTextRect.bottom );
- DrawString( theString );
- DrawString( "\p " );
- }
- MoveTo( gMPTextRect.left, gMPTextRect.bottom );
- if (*(char *)0x17b & 2)
- DrawString("\p1 ");
- else
- DrawString("\p4 ");
-
- #if 0
- if( startTick != -1 ) {
- float percentOfTotal = (timeNow - startMovieTime) / (float)srcMovieDuration;
- float totalDuration = (1.0 / percentOfTotal) * (endTick - startTick);
- float ticksRemaining = totalDuration * (1.0 - ((float)timeNow / (float)srcMovieDuration));
- float secondsRemaining = ticksRemaining / 60;
- if (*(char *)0x17b)
- ticksRemaining += 0.00001;
-
- fPNumToString( secondsRemaining, theString, 2 );
- MoveTo( gTimeRemainingTextRect.left, gTimeRemainingTextRect.bottom );
- DrawString(theString);
- DrawString( "\p " );
- }
- #endif
- }
-
- return( quit );
- }
-
- /*==================================================================================*/
- void fSetRGBColor( RGBColor *theColor, short r, short g, short b ) {
-
- theColor->red = r * 256;
- theColor->green = g * 256;
- theColor->blue = b * 256;
- }
-
- /*==================================================================================*/
- void fPNumToString( float theNum, Str255 theString, short fix ) {
-
- short i;
- Boolean negative;
- long wholeNum;
- float fraction;
- long fractNum;
- Str255 fractString;
- short padCount;
-
- negative = false;
- if( theNum < 0 ) {
- negative = true;
- theNum = -theNum;
- }
-
- /* Round the number off before proceeding */
- fraction = 0.500001;
- for( i = 0; i < fix; i++ )
- fraction /= 10;
- theNum += fraction;
-
- /* Set up whole number portion of the string */
- wholeNum = theNum;
-
- /* Set up fractional portion of string */
- fraction = theNum - wholeNum;
- for( i = 0; i < fix; i++ )
- fraction *= 10;
- fractNum = fraction;
-
- /* Build the string */
- NumToString( wholeNum, theString );
- theString[++theString[0]] = '.';
- NumToString( fractNum, fractString );
- padCount = fix - fractString[0];
- for( i = 0; i < padCount; i++ )
- theString[++theString[0]] = '0';
- fPStrConcat( theString, fractString );
-
- /* Strip trailing zero's (except the one after the decimal place if any) */
- while( theString[theString[0]] == '0' &&
- theString[theString[0] - 1] != '.' &&
- theString[0] > 3 )
- theString[0]--;
-
- if( negative ) {
- BlockMove( &theString[1], &theString[2], theString[0] );
- theString[1] = '-';
- theString[0]++;
- }
- }
-
- /*==================================================================================*/
- void fPStrCopy( Str255 s1, Str255 s2 ) {
- /* Copies pascal string s2 into s1 (bowing to strcpy() parameter ordering). */
-
- BlockMove( s2, s1, 255 < s2[0] + 1 ? 255 : s2[0] + 1 );
- }
-
- /*==================================================================================*/
- void fPStrConcat( Str255 s1, Str255 s2 ) {
- /* Attaches pascal string s2 to pascal string s1. */
-
- short i;
-
- i = 255 - s1[0] < s2[0] ? 255 - s1[0] : s2[0];
- BlockMove( &s2[1], &s1[s1[0] + 1], i );
- s1[0] += i;
- }
-
- /*==================================================================================*/
-
-
- pascal OSErr AEOpenDoc(AppleEvent *message, AppleEvent *reply,long refCon);
- OSErr MissedAEParameters (AppleEvent *message);
-
- Boolean getMovieFile(FSSpec *theFile)
- {
- Boolean result = false;
- unsigned long gStartTicks = LMGetTicks();
- void *upp = NewAEEventHandlerProc(AEOpenDoc);
-
- theFile->vRefNum = 0;
-
- AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, upp, (long)theFile, false);
-
- while (gStartTicks + 30 > (unsigned long)LMGetTicks()) {
- EventRecord event;
-
- WaitNextEvent(everyEvent, &event, 0, 0);
- if (event.what == kHighLevelEvent)
- AEProcessAppleEvent(&event);
- }
-
- AERemoveEventHandler(kCoreEventClass, kAEOpenDocuments, upp, false);
-
- if (theFile->vRefNum == 0) {
- StandardFileReply reply;
- SFTypeList types;
-
- types[0] = MovieFileType;
- StandardGetFilePreview(nil, 1, types, &reply);
-
- result = reply.sfGood;
- if (result)
- *theFile = reply.sfFile;
- }
- else
- result = true;
-
- return result;
- }
-
- pascal OSErr AEOpenDoc(AppleEvent *message, AppleEvent *,long refCon)
- {
- FSSpec fss;
- AEDescList docList;
- long index, itemsInList;
- Size actualSize;
- AEKeyword keywd;
- DescType typeCode;
- OSErr err;
- FSSpec *filePtr = (FSSpec *)refCon;
-
- err = AEGetParamDesc(message, keyDirectObject, typeAEList, &docList);
- if(err) goto bail;
-
- err = MissedAEParameters(message);
- if(err) goto bail;
-
- err = AECountItems(&docList, &itemsInList);
- if(err) goto bail;
-
- for (index = 1; index <= itemsInList; index++) {
- HFileInfo pb;
-
- err = AEGetNthPtr(&docList, index, typeFSS, &keywd, &typeCode,
- (Ptr)&fss, sizeof(FSSpec), &actualSize);
- if(err) goto bail;
-
- // need to figure out if this is a directory or a file
-
- pb.ioVRefNum = fss.vRefNum;
- pb.ioFDirIndex = 0;
- pb.ioDirID = fss.parID;
- pb.ioNamePtr = fss.name;
- err = PBGetCatInfoSync((void *)&pb);
- if (!err) {
- if (pb.ioFlAttrib & 16) {
- fss.parID = pb.ioDirID;
- }
- else {
- *filePtr = fss;
- break;
- }
- }
- }
-
- err = AEDisposeDesc(&docList);
-
- bail:
- return err;
- }
-
- OSErr MissedAEParameters (AppleEvent *message)
- {
- DescType typeCode;
- Size actualSize;
- OSErr err;
-
- err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
- &typeCode, nil, 0L, &actualSize);
- if (err == errAEDescNotFound)
- return(noErr);
- return(err = noErr ? errAEEventNotHandled : err);
- }
-
- OSErr FindAProcess(OSType typeToFind, OSType creatorToFind, ProcessSerialNumberPtr processSN);
-
- /* OpenSelection takes a FSSpec pointer, and creates a Finder Open Selection */
- /* AppleEvent for the document described by the FSSpec. This can be an */
- /* application or document. */
- OSErr OpenSelection(FSSpecPtr theDocToOpen)
- {
- OSErr err;
- AppleEvent aeEvent;
- AEDesc myAddressDesc, aeDirDesc, listElem;
- FSSpec dirSpec;
- AEDesc fileList;
- ProcessSerialNumber process;
- AliasHandle DirAlias = nil, FileAlias = nil;
-
- /* go find the Finder's process information, please */
- if (FindAProcess('FNDR', 'MACS', &process))
- return procNotFound;
-
- myAddressDesc.dataHandle = nil;
- aeDirDesc.dataHandle = nil;
- listElem.dataHandle = nil;
- fileList.dataHandle = nil;
- aeEvent.dataHandle = nil;
-
- /* Create an address descriptor so the AppleEvent manager knows where to send this event */
- if (err = AECreateDesc(typeProcessSerialNumber, (Ptr)&process, sizeof(process), &myAddressDesc))
- goto bail;
-
- /* Create the empty FinderEvent */
- /* it's a Finder 'FNDR', Open Selection 'sope' event */
- if (err = AECreateAppleEvent('FNDR', 'sope', &myAddressDesc, kAutoGenerateReturnID, kAnyTransactionID, &aeEvent))
- goto bail;
-
- /* make a FSSpec for the parent folder (see the OpenSelection description in the AE Registry ) */
- /* using the information in the document FSSpec */
- if (err = FSMakeFSSpec(theDocToOpen->vRefNum, theDocToOpen->parID, nil, &dirSpec))
- goto bail;
- if (err = NewAliasMinimal(&dirSpec, &DirAlias))
- goto bail;
-
- /* Create alias for file */
- if (err = NewAliasMinimal(theDocToOpen, &FileAlias))
- goto bail;
-
- /* Create the file list */
- if (err = AECreateList(nil, 0, false, &fileList))
- goto bail;
-
- /* create the folder descriptor */
- HLock((Handle)DirAlias);
- err = AECreateDesc(typeAlias, (void *)*DirAlias, GetHandleSize((Handle)DirAlias), &aeDirDesc);
- if (err) goto bail;
- DisposeHandle((Handle)DirAlias);
- DirAlias = nil;
-
- /* put the Directory Desc in the event as the direct object */
- if ((err = AEPutParamDesc(&aeEvent, keyDirectObject, &aeDirDesc)) == noErr) {
- AEDisposeDesc(&aeDirDesc);
- aeDirDesc.dataHandle = nil;
-
- /* create the file descriptor and add to aliasList */
- HLock((Handle)FileAlias);
- err = AECreateDesc(typeAlias, (void *)*FileAlias, GetHandleSize((Handle)FileAlias), &listElem);
- if (err) goto bail;
- DisposeHandle((Handle)FileAlias);
- FileAlias = nil;
-
- err = AEPutDesc(&fileList, 0, &listElem);
- if (err) goto bail;
- }
-
- AEDisposeDesc(&listElem);
- listElem.dataHandle = nil;
-
- /* Add the file alias list to the event */
- if (err = AEPutParamDesc(&aeEvent, 'fsel', &fileList))
- goto bail;
-
- AEDisposeDesc(&fileList);
- fileList.dataHandle = nil;
-
- /* And now send the event! */
- err = AESend(&aeEvent, nil, kAENoReply | kAENeverInteract | kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout, nil, nil);
- if (err == noPortErr) {
- err = AESend(&aeEvent, nil, kAENoReply | kAENeverInteract | kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout, nil, nil);
- }
-
- bail:
- AEDisposeDesc(&aeEvent);
- AEDisposeDesc(&myAddressDesc);
- AEDisposeDesc(&aeDirDesc);
- AEDisposeDesc(&listElem);
- AEDisposeDesc(&fileList);
- AEDisposeDesc(&aeEvent);
- DisposeHandle((Handle)DirAlias);
- DisposeHandle((Handle)FileAlias);
-
- return err;
- }
-
-
- OSErr FindAProcess(OSType typeToFind, OSType creatorToFind, ProcessSerialNumberPtr processSN)
- {
- OSErr err;
- ProcessInfoRec tempInfo;
-
- processSN->lowLongOfPSN = kNoProcess;
- processSN->highLongOfPSN = kNoProcess;
-
- tempInfo.processInfoLength = sizeof(ProcessInfoRec);
- tempInfo.processName = nil;
- tempInfo.processAppSpec = nil;
-
- do {
- if (err = GetNextProcess(processSN))
- break;
-
- GetProcessInformation(processSN, &tempInfo);
- } while ((tempInfo.processSignature != creatorToFind) && (tempInfo.processType != typeToFind));
-
- return err;
- }
-